package okw.gui;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import okw.database.model.Node;
import okw.manager.ManagerController;

import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;

import core.utils.DialogPositioner;

public class DlgCommunicationState extends Dialog {
	private class ContentProvider implements IStructuredContentProvider {
		public Object[] getElements(Object inputElement) {
			List<CommunicationNodeState> communicationNodeStates = new ArrayList<CommunicationNodeState>();
			for (Node node : nodeList) {
				communicationNodeStates.add(locatorUriToNodeStateMap.get(node.getLocatorURI()));
			}
			return communicationNodeStates.toArray();
		}

		public void dispose() {
		}

		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		}
	}

	private ManagerController manager;

	private List<Node> nodeList;

	private Map<String, CommunicationNodeState> locatorUriToNodeStateMap = new HashMap<String, CommunicationNodeState>();

	protected Object result;
	protected Shell shell;

	private TableViewer tblVwrCommunicationState;
	private Table tblCommunicationState;
	private TableColumn tblclmnNode;
	private TableViewerColumn tblVwrClmnNode;
	private TableColumn tblclmnState;
	private TableViewerColumn tblVwrClmnState;
	private Button btnOK;
	private TableColumn tblclmnType;
	private TableViewerColumn tblVwrClmnType;

	/**
	 * Create the dialog.
	 * 
	 * @param parent
	 * @param style
	 */
	public DlgCommunicationState(Shell parent, ManagerController manager) {
		super(parent, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.APPLICATION_MODAL);

		this.manager = manager;
		this.nodeList = manager.getNeighborNodes();

		for (Node node : nodeList) {
			String name = node.getName() + "[" + node.getLocatorURI() + "]";
			String type = node.getLevel() == 1 ? "Above" : "Below";
			String state = "?";
			locatorUriToNodeStateMap.put(node.getLocatorURI(), new CommunicationNodeState(name, type, state));
		}

		setText("Communication state");

		shell = new Shell(getParent(), getStyle());
		shell.setSize(575, 400);
		shell.setText(getText());
	}

	/**
	 * Open the dialog.
	 * 
	 * @return the result
	 */
	public Object open() {
		createContents();
		shell.open();
		shell.layout();
		DialogPositioner.centerShell(shell);

		Display display = getParent().getDisplay();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
		return result;
	}

	/**
	 * Create contents of the dialog.
	 */
	private void createContents() {
		shell.setLayout(new GridLayout(1, false));

		tblVwrCommunicationState = new TableViewer(shell, SWT.BORDER | SWT.FULL_SELECTION);
		tblCommunicationState = tblVwrCommunicationState.getTable();
		tblCommunicationState.setHeaderVisible(true);
		tblCommunicationState.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));

		tblVwrClmnNode = new TableViewerColumn(tblVwrCommunicationState, SWT.NONE);
		tblVwrClmnNode.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : ((CommunicationNodeState) element).getName();
			}
		});
		tblclmnNode = tblVwrClmnNode.getColumn();
		tblclmnNode.setWidth(290);
		tblclmnNode.setText("Node");

		tblVwrClmnType = new TableViewerColumn(tblVwrCommunicationState, SWT.NONE);
		tblVwrClmnType.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : ((CommunicationNodeState) element).getType();
			}
		});
		tblclmnType = tblVwrClmnType.getColumn();
		tblclmnType.setWidth(100);
		tblclmnType.setText("Type");

		tblVwrClmnState = new TableViewerColumn(tblVwrCommunicationState, SWT.NONE);
		tblVwrClmnState.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : ((CommunicationNodeState) element).getState();
			}
		});
		tblclmnState = tblVwrClmnState.getColumn();
		tblclmnState.setWidth(100);
		tblclmnState.setText("State");
		tblVwrCommunicationState.setContentProvider(new ContentProvider());

		btnOK = new Button(shell, SWT.NONE);
		btnOK.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				shell.close();
			}
		});
		GridData gdBtnClose = new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1);
		gdBtnClose.widthHint = 100;
		btnOK.setLayoutData(gdBtnClose);
		btnOK.setText("OK");
		tblVwrCommunicationState.setInput(nodeList);
		manager.checkCommunication(this);
	}

	public void updateNodeState(final String locatorUri, final Boolean state) {
		Display.getDefault().asyncExec(new Runnable() {
			@Override
			public void run() {
				CommunicationNodeState communicationNodeState = locatorUriToNodeStateMap.get(locatorUri);
				if (communicationNodeState != null) {
					if (state)
						communicationNodeState.setState("Success");
					else
						communicationNodeState.setState("Failure");
					tblVwrCommunicationState.refresh();
				}
			}
		});
	}

	class CommunicationNodeState {
		private String name;
		private String type;
		private String state;

		public CommunicationNodeState(String name, String type, String state) {
			this.name = name;
			this.type = type;
			this.state = state;
		}

		public String getName() {
			return name;
		}

		public String getType() {
			return type;
		}

		public void setState(String state) {
			this.state = state;
		}

		public String getState() {
			return state;
		}
	}
}
